다중 쓰레드 환경에서 안전하게 생성자 작성하기
· 약 7분
(원문: Java theory and practice: Safe construction techniques)[http://www.ibm.com/developerworks/library/j-jtp0618/]
Race condition(위험한 경쟁상황을 만들지 말자)
sample codes
Listing 1.
public class DataRace {
static int a = 0; // target for race condition.
public static void main(){
new MyThread().start();
a = 1;
}
public static class MyThread extends Thread {
public void run(){
System.out.println(a); // print 0 ? or 1, you can't sure for that.
}
}
}
위의 코드를 보고 음~ 별 문제 없내라고 생각할 수 도 있다. 왜냐면 위의 코드를 실행하면 거의 대부분 예상대로 1을 출력할 것이기 때문이다. (0을 출력할 것이라고 생각할 수도 있겠지만) 그건 실제로 어떤 개발 환경인지, 어떤 JDK를 사용하는지, Thread 스케쥴링을 어떻게 하는지에 따라 결과는 0 혹은 1이 될 수 있다. 즉, 특정 조건에 따라 값이 바뀔 수 있다는 것. 그러면 안되는데…
그 이유는 서브 쓰레드(MyThread)가 a 변수에 대한 가시성(visibility)에 대해 메인 쓰레드와 경쟁하는 상황이 만들어 지기 때문이다. 그럼 서브 쓰레드와 메인 쓰레드간 a에 대한 경쟁을 없애주면 해결 이 될 것이므로, 아래와 같이 코드를 변경하는 것이 좋을 것으로 생각된다. (아니면 큰일날까?)
public class DataRace {
private int a = 0; // target for race condition.
public final synchronized void setA(int a){
this.a = a;
}
public final synchronized int getA(){
return this.a;
}
public static void main(String[] args) {
DataRace dr = new DataRace();
dr.setA(1);
new MyThread(dr.getA()).start();
}
public static class MyThread extends Thread {
private final int a;
public MyThread(int a){
this.a = a;
}
public void run(){
System.out.println(a);
}
}
}
